package com.lonely.inventory.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Tuple;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lonely.common.core.page.Condition;
import com.lonely.common.enums.CommonStatus;
import com.lonely.common.enums.DataScope;
import com.lonely.common.exception.BusinessException;
import com.lonely.common.threadlocals.DataPermissionThreadLocal;
import com.lonely.common.utils.SecurityUtils;
import com.lonely.inventory.domain.dto.surplus.*;
import com.lonely.inventory.domain.entity.SysInventoryStorageArchive;
import com.lonely.inventory.domain.entity.SysSurplusInventory;
import com.lonely.inventory.domain.entity.SysSurplusInventorySizeInfo;
import com.lonely.inventory.domain.vo.surplus.SurplusInventoryPageQueryVo;
import com.lonely.inventory.domain.vo.surplus.SurplusInventorySizeInfoVo;
import com.lonely.inventory.mapper.SysSurplusInventoryMapper;
import com.lonely.inventory.service.*;
import com.lonely.order.domain.dto.api.NumberInfo;
import com.lonely.order.domain.dto.order.SkcStickerQrCodeDTO;
import com.lonely.order.domain.entity.SysOrder;
import com.lonely.order.domain.vo.order.OrderQuantityInfo;
import com.lonely.order.service.IOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author : 黄志标
 * @date: 2025/9/19 10:03
 * @description: 尾货库存服务实现类
 */
@Service
public class SurplusInventoryServiceImpl extends ServiceImpl<SysSurplusInventoryMapper, SysSurplusInventory> implements ISurplusInventoryService {

    @Autowired
    private ISurplusInventorySizeInfoService surplusInventorySizeInfoService;

    @Autowired
    private IOrderService orderService;

    @Autowired
    private IStorageArchiveService storageArchiveService;

    @Autowired
    private ISurplusInventoryLogService surplusInventoryLogService;

    @Autowired
    private ISurplusInventoryFlowWaterService surplusInventoryFlowWaterService;

    /**
     * 分页查询
     *
     * @param queryDto
     * @return
     */
    @Override
    public Page<SurplusInventoryPageQueryVo> page(SurplusInventoryPageQueryDto queryDto) {
        DataPermissionThreadLocal.setDataPermission(DataScope.ORDER_FACTORY, "o.factory_permission");
        Page<SurplusInventoryPageQueryVo> page = Condition.page(queryDto);
        page = super.getBaseMapper().page(page, queryDto);

        if (CollUtil.isNotEmpty(page.getRecords())) {
//            // 获取尾货库存对应的订单颜色映射信息
//            List<Long> orderIds = page.getRecords().stream().map(SurplusInventoryPageQueryVo::getOrderId).distinct().collect(Collectors.toList());
//            Map<Long, String> orderColorMap = this.orderService.listByIds(orderIds).stream().collect(Collectors.toMap(BaseEntity::getId, SysOrder::getColor, (x, y) -> x));

            // 获取尾货库存与尺码的映射信息
            List<Long> surplusInventoryIds = page.getRecords().stream().map(SurplusInventoryPageQueryVo::getId).collect(Collectors.toList());
            Map<Long, List<SysSurplusInventorySizeInfo>> surplusInventorySizeMap = this.surplusInventorySizeInfoService.list(new LambdaQueryWrapper<SysSurplusInventorySizeInfo>()
                    .in(SysSurplusInventorySizeInfo::getSurplusInventoryId, surplusInventoryIds)
                    .gt(SysSurplusInventorySizeInfo::getInventoryStockQuantity, 0)
                    .eq(SysSurplusInventorySizeInfo::getStatus, CommonStatus.ENABLE.code)
            ).stream().collect(Collectors.groupingBy(SysSurplusInventorySizeInfo::getSurplusInventoryId));

            page.setRecords(page.getRecords().stream().peek(x -> {
                if (!surplusInventorySizeMap.containsKey(x.getId())) {
                    return;
                }

                List<SurplusInventorySizeInfoVo> sizeInfos = surplusInventorySizeMap.get(x.getId()).stream().map(currentSize -> {
                    SurplusInventorySizeInfoVo surplusInventorySizeInfoVo = new SurplusInventorySizeInfoVo();
                    surplusInventorySizeInfoVo.setSurplusInventoryId(currentSize.getSurplusInventoryId());
                    surplusInventorySizeInfoVo.setColor(x.getColor());
                    surplusInventorySizeInfoVo.setSizeName(currentSize.getSizeName());
                    surplusInventorySizeInfoVo.setInventoryStockQuantity(currentSize.getInventoryStockQuantity());
                    return surplusInventorySizeInfoVo;
                }).collect(Collectors.toList());
                x.setSizeInfos(sizeInfos);
            }).collect(Collectors.toList()));

        }

        return page;
    }

    /**
     * 更新尾货库存备注信息
     *
     * @param submitDto
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void submitRemark(EditSurplusInventoryRemarkDto submitDto) {
        SysSurplusInventory surplusInventory = super.getById(submitDto.getSurplusInventoryId());
        Assert.notNull(surplusInventory, "该尾货库存数据不存在");

        surplusInventory.setRemark(submitDto.getRemark());
        surplusInventory.setUpdateBy(SecurityUtils.getUserId());
        super.updateById(surplusInventory);
    }

    /**
     * 根据尾货库存id获取对应的尺码库存数量信息
     *
     * @param surplusInventoryId
     * @return
     */
    @Override
    public OrderQuantityInfo getSurplusInventoryStockQuantityInfo(Long surplusInventoryId) {

        List<SysSurplusInventorySizeInfo> sizeInfos = this.surplusInventorySizeInfoService.list(new LambdaQueryWrapper<SysSurplusInventorySizeInfo>()
                .eq(SysSurplusInventorySizeInfo::getSurplusInventoryId, surplusInventoryId)
                .eq(SysSurplusInventorySizeInfo::getStatus, CommonStatus.ENABLE.code)
        );

        List<OrderQuantityInfo.Column> columns = new ArrayList<>();
        List<Map<String, Object>> datas = new ArrayList<>();

        // 添加默认列
        columns.add(new OrderQuantityInfo.Column().setTitle("尺码").setKey("type"));

        // 处理下单件数
        if (CollUtil.isNotEmpty(sizeInfos)) {
            // 提取所有的尺码
            List<String> sizeNames = sizeInfos.stream().map(SysSurplusInventorySizeInfo::getSizeName).collect(Collectors.toList());
            sizeNames.forEach(sizeName -> {
                columns.add(new OrderQuantityInfo.Column().setKey(sizeName).setTitle(sizeName));
            });

            // 表格数据
            Map<String, Object> sizeData = new LinkedHashMap<>();
            sizeData.put("type", "尾货库存数");
            sizeInfos.forEach(currentSize -> {
                sizeData.put(currentSize.getSizeName(), currentSize.getInventoryStockQuantity());
            });
            int totalQuantity = sizeInfos.stream().mapToInt(SysSurplusInventorySizeInfo::getInventoryStockQuantity).sum();
            sizeData.put("total", totalQuantity);
            datas.add(sizeData);
        }

        // 添加合计列
        columns.add(new OrderQuantityInfo.Column().setTitle("合计").setKey("total"));
        return new OrderQuantityInfo().setColumns(columns).setData(datas);

    }

    /**
     * 更新尾货库存
     *
     * @param submitDto
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void editSurplusInventory(EditSurplusInventoryDTO submitDto) {
        SysSurplusInventory surplusInventory = super.getById(submitDto.getSurplusInventoryId());
        Assert.notNull(surplusInventory, "该尾货库存数据不存在");

        // 提取对应的尺码信息
        OrderQuantityInfo sizeInfo = submitDto.getSizeInfo();
        Map<String, Object> sizeQuantityInfoData = Optional.ofNullable(sizeInfo.getData()).orElse(new ArrayList<>()).stream().filter(x -> x.containsKey("type"))
                .filter(x -> Objects.equals(x.get("type"), "尾货库存数")).findFirst().orElse(null);
        if (sizeQuantityInfoData == null) {
            throw new BusinessException("没有找到关于尾货库存数相关数据");
        }

        // 提取具体的尺码
        List<String> sizeNames = sizeQuantityInfoData.keySet().stream().filter(x -> !Objects.equals(x, "type"))
                .filter(x -> !Objects.equals(x, "total")).collect(Collectors.toList());

        // 修改前的数据
        List<SysSurplusInventorySizeInfo> oldInventorySizeInfos = this.surplusInventorySizeInfoService.list(new LambdaQueryWrapper<SysSurplusInventorySizeInfo>()
                .eq(SysSurplusInventorySizeInfo::getSurplusInventoryId, surplusInventory.getId())
                .in(SysSurplusInventorySizeInfo::getSizeName, sizeNames)
                .eq(SysSurplusInventorySizeInfo::getStatus, CommonStatus.ENABLE.code)
        );

        // 执行数量更新
        List<EditSurplusInventorySizeQuantityDto> sizeQuantityDtos = sizeNames.stream().map(x -> {
            EditSurplusInventorySizeQuantityDto inventorySizeQuantityDto = new EditSurplusInventorySizeQuantityDto();
            inventorySizeQuantityDto.setSurplusInventoryId(submitDto.getSurplusInventoryId());
            inventorySizeQuantityDto.setSizeName(x);
            inventorySizeQuantityDto.setQuantity(MapUtil.getInt(sizeQuantityInfoData, x, 0));
            return inventorySizeQuantityDto;
        }).collect(Collectors.toList());
        Map<String, Tuple> comparisonData = this.surplusInventorySizeInfoService.updateSizeQuantityInfo(sizeQuantityDtos);

        // 添加操作日志
        this.surplusInventoryLogService.editSurplusInventoryLog(surplusInventory, comparisonData);

        // 添加流水
        List<SysSurplusInventorySizeInfo> newInventorySizeInfos = sizeNames.stream().map(x -> {
            SysSurplusInventorySizeInfo inventorySizeInfo = new SysSurplusInventorySizeInfo();
            inventorySizeInfo.setSurplusInventoryId(surplusInventory.getId());
            inventorySizeInfo.setSizeName(x);
            inventorySizeInfo.setInventoryStockQuantity(MapUtil.getInt(sizeQuantityInfoData, x, 0));
            return inventorySizeInfo;
        }).collect(Collectors.toList());
        this.surplusInventoryFlowWaterService.addFlowWater(surplusInventory, oldInventorySizeInfos, newInventorySizeInfos);
    }

    /**
     * 查询指定订单的尾货库存尺码库存数量初始化信息
     *
     * @param produceOrderId
     * @return
     */
    @Override
    public OrderQuantityInfo getInitSurplusInventorySizeInfo(Long produceOrderId) {
        SysOrder sysOrder = this.orderService.getOne(new LambdaQueryWrapper<SysOrder>().eq(SysOrder::getProduceOrderId, produceOrderId));
        Assert.notNull(sysOrder, "订单不存在");

        List<OrderQuantityInfo.Column> columns = new ArrayList<>();
        List<Map<String, Object>> datas = new ArrayList<>();

        // 添加默认列
        columns.add(new OrderQuantityInfo.Column().setTitle("尺码").setKey("type"));

        if (StrUtil.isNotEmpty(sysOrder.getOrderInfo())) {
            List<NumberInfo> orderInfoNumbers = JSON.parseArray(sysOrder.getOrderInfo(), NumberInfo.class);
            if (CollUtil.isNotEmpty(orderInfoNumbers)) {
                // 提取所有的尺码
                List<String> sizeNames = orderInfoNumbers.stream().map(NumberInfo::getSizeName).collect(Collectors.toList());
                sizeNames.forEach(sizeName -> columns.add(new OrderQuantityInfo.Column().setKey(sizeName).setTitle(sizeName)));

                // 处理订单数
                Map<String, Object> sizeData = new LinkedHashMap<>();
                sizeData.put("type", "待入库数");
                orderInfoNumbers.forEach(numberInfo -> {
                    sizeData.put(numberInfo.getSizeName(), numberInfo.getQuantity());
                });
                sizeData.put("total", sysOrder.getQuantity());
                datas.add(sizeData);

                // 非套装
                Map<String, Object> initSurplusInventoryQuantityData = new LinkedHashMap<>();
                initSurplusInventoryQuantityData.put("type", "实入库数");
                for (String sizeName : sizeNames) {
                    initSurplusInventoryQuantityData.put(sizeName, 0);
                }
                initSurplusInventoryQuantityData.put("total", 0);
                datas.add(initSurplusInventoryQuantityData);
            }
        }

        // 添加合计列
        columns.add(new OrderQuantityInfo.Column().setTitle("合计").setKey("total"));
        return new OrderQuantityInfo().setColumns(columns).setData(datas);
    }

    /**
     * 新增尾货库存
     *
     * @param submitDto
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addSurplusInventory(AddSurplusInventoryDTO submitDto) {
        SysOrder sysOrder = this.orderService.getOne(new LambdaQueryWrapper<SysOrder>()
                .eq(SysOrder::getProduceOrderId, submitDto.getProduceOrderId())
        );
        Assert.notNull(sysOrder, "订单不存在");

        SysInventoryStorageArchive storageArchive = this.storageArchiveService.getById(submitDto.getSurplusInventoryId());
        Assert.notNull(storageArchive, "库位不存在");

        // 提取对应的尺码信息
        OrderQuantityInfo sizeInfo = submitDto.getSizeInfo();
        Map<String, Object> sizeQuantityInfoData = Optional.ofNullable(sizeInfo.getData()).orElse(new ArrayList<>()).stream().filter(x -> x.containsKey("type"))
                .filter(x -> Objects.equals(x.get("type"), "实入库数")).findFirst().orElse(null);
        if (sizeQuantityInfoData == null) {
            throw new BusinessException("没有找到关于尾货库存数相关数据");
        }

        // 提取具体的尺码,过滤出入库数为0的尺码数据
        List<String> sizeNames = sizeQuantityInfoData.entrySet().stream().filter(x -> !Objects.equals(x.getKey(), "type"))
                .filter(x -> !Objects.equals(x.getKey(), "total"))
                .filter(x -> Convert.toInt(x.getValue(), 0) != 0)
                .map(Map.Entry::getKey)
                .collect(Collectors.toList());
        if (CollUtil.isEmpty(sizeNames)) {
            throw new BusinessException("没有待入库的尺码数据");
        }

        // 构建数据入库
        SysSurplusInventory sysSurplusInventory = new SysSurplusInventory();
        sysSurplusInventory.setOrderId(sysOrder.getId());
        sysSurplusInventory.setProduceOrderId(String.valueOf(sysOrder.getProduceOrderId()));
        sysSurplusInventory.setSkc(sysOrder.getSku());
        sysSurplusInventory.setStorageArchiveId(storageArchive.getId());
        sysSurplusInventory.setCreateBy(SecurityUtils.getUserId());
        sysSurplusInventory.setUpdateBy(SecurityUtils.getUserId());
        super.save(sysSurplusInventory);

        // 添加尾货库存尺码信息
        List<SysSurplusInventorySizeInfo> sysSurplusInventorySizeInfos = new ArrayList<>();
        for (String sizeName : sizeNames) {
            SysSurplusInventorySizeInfo sysSurplusInventorySizeInfo = new SysSurplusInventorySizeInfo();
            sysSurplusInventorySizeInfo.setSurplusInventoryId(sysSurplusInventory.getId());
            sysSurplusInventorySizeInfo.setSizeName(sizeName);
            sysSurplusInventorySizeInfo.setInventoryStockQuantity(MapUtil.getInt(sizeQuantityInfoData, sizeName, 0));
            sysSurplusInventorySizeInfo.setCreateBy(SecurityUtils.getUserId());
            sysSurplusInventorySizeInfo.setUpdateBy(SecurityUtils.getUserId());
            sysSurplusInventorySizeInfos.add(sysSurplusInventorySizeInfo);
        }
        this.surplusInventorySizeInfoService.saveBatch(sysSurplusInventorySizeInfos);

        // 添加日志
        this.surplusInventoryLogService.addSurplusInventoryLog(sysSurplusInventory, sysSurplusInventorySizeInfos);

        // 添加流水
        this.surplusInventoryFlowWaterService.addFlowWater(sysSurplusInventory, null, sysSurplusInventorySizeInfos);
    }

    /**
     * 尾货上架
     *
     * @param submitDto
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void surplusStockPutAway(SurplusStockPutAwayDTO submitDto) {
        SysInventoryStorageArchive storageArchive = this.storageArchiveService.getByStorageCode(submitDto.getStorageCode());
        Assert.notNull(storageArchive, "没有查询到库位信息..");

        // 将相同订单号合并
        Map<String, List<SkcStickerQrCodeDTO>> orderMap = submitDto.getSkcStickerCodes().stream().collect(Collectors.groupingBy(SkcStickerQrCodeDTO::getProduceOrderId));
        List<String> produceOrderIds = new ArrayList<>(orderMap.keySet());
        Map<Long, SysOrder> produceOrderMap = this.orderService.list(new LambdaQueryWrapper<SysOrder>()
                .in(SysOrder::getProduceOrderId, produceOrderIds)
        ).stream().collect(Collectors.toMap(SysOrder::getProduceOrderId, Function.identity(), (x, y) -> x));


        for (Map.Entry<String, List<SkcStickerQrCodeDTO>> currentEntry : orderMap.entrySet()) {
            // 将相同尺码进行合并
            Map<String, Long> sizeCountMap = currentEntry.getValue().stream().collect(Collectors.groupingBy(SkcStickerQrCodeDTO::getSizeName, Collectors.counting()));

            SysOrder sysOrder = produceOrderMap.get(Long.valueOf(currentEntry.getKey()));

            // 新建尾货库存信息
            SysSurplusInventory sysSurplusInventory = new SysSurplusInventory();
            sysSurplusInventory.setOrderId(sysOrder.getId());
            sysSurplusInventory.setProduceOrderId(currentEntry.getKey());
            sysSurplusInventory.setSkc(sysOrder.getSku());
            sysSurplusInventory.setStorageArchiveId(storageArchive.getId());
            sysSurplusInventory.setCreateBy(SecurityUtils.getUserId());
            sysSurplusInventory.setUpdateBy(SecurityUtils.getUserId());
            super.save(sysSurplusInventory);

            // 新建尾货库存明细信息
            List<SysSurplusInventorySizeInfo> sysSurplusInventorySizeInfos = new ArrayList<>();
            for (Map.Entry<String, Long> currentSize : sizeCountMap.entrySet()) {
                SysSurplusInventorySizeInfo sysSurplusInventorySizeInfo = new SysSurplusInventorySizeInfo();
                sysSurplusInventorySizeInfo.setSurplusInventoryId(sysSurplusInventory.getId());
                sysSurplusInventorySizeInfo.setSizeName(currentSize.getKey());
                sysSurplusInventorySizeInfo.setInventoryStockQuantity(Convert.toInt(currentSize.getValue()));
                sysSurplusInventorySizeInfo.setCreateBy(SecurityUtils.getUserId());
                sysSurplusInventorySizeInfo.setUpdateBy(SecurityUtils.getUserId());
                sysSurplusInventorySizeInfos.add(sysSurplusInventorySizeInfo);
            }
            this.surplusInventorySizeInfoService.saveBatch(sysSurplusInventorySizeInfos);

            // 添加日志
            this.surplusInventoryLogService.putAwaySurplusInventoryLog(sysSurplusInventory, sysSurplusInventorySizeInfos);

            // 添加流水
            this.surplusInventoryFlowWaterService.addFlowWater(sysSurplusInventory, null, sysSurplusInventorySizeInfos);
        }

    }
}
